Skip to content

fix: repair sandbox browser driver lifecycle - #186

Merged
iamjr15 merged 1 commit into
mainfrom
fix/browser-driver-lifecycle
Aug 8, 2026
Merged

fix: repair sandbox browser driver lifecycle#186
iamjr15 merged 1 commit into
mainfrom
fix/browser-driver-lifecycle

Conversation

@iamjr15

@iamjr15 iamjr15 commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fixes browser initialization that was blocked by the driver's own global provider-fetch restriction.
  • Gives the driver explicit ownership of Chromium so startup failures and shutdowns cannot leak browser processes.
  • Makes readiness represent a fully initialized Stagehand context and reduces stale-driver detection from 90 seconds to 5 seconds.
  • Disables PTY echo before credentials are delivered over stdin so secrets cannot enter Daytona session logs.

Context

Production acceptance QA exposed this incident directly; there is no separate Linear issue or plan document.

Architecture

The browser driver now has two explicit transport boundaries:

  1. A provider-scoped, response-bounded fetch implementation injected into Stagehand's AI SDK client.
  2. Native loopback CDP transport whose WebSocket endpoint is fetched with a byte limit and validated against the exact owned Chromium port.

The driver launches Chromium itself, attaches Stagehand through the validated CDP URL, and retains the launch handle for deterministic cleanup. The readiness endpoint returns success only after Stagehand and the browser connection guard are installed.

Decisions Made

Decision Choice Alternatives Considered Reasoning
Provider egress enforcement Inject a restricted fetch into the AI SDK provider Replace global fetch and allow-list local CDP Keeps provider security policy scoped to provider I/O and cannot interfere with browser internals
Chromium lifecycle Driver-owned chrome-launcher process Let Stagehand launch Chromium Gives the driver a handle that can always be killed, including partial initialization failures
Readiness Eager initialization with stateful readiness Lazy initialization from health/actions Prevents the process manager from accepting an unusable driver
Credential delivery Disable PTY echo before stdin bootstrap Redact logs after capture Prevents secret persistence at the source

Edge Cases Handled

Scenario Handling
CDP response is oversized or points off loopback Reject before Stagehand attaches
Stagehand fails after Chromium launches Close Stagehand, kill the exact Chromium process, log a sanitized diagnostic, and exit non-zero
Driver receives SIGINT, SIGTERM, or expires Close Stagehand and kill the owned Chromium process
Existing driver is stale Health probe fails after 5 seconds and is replaced
Daytona PTY echoes stdin Echo is disabled before bootstrap input is sent
Diagnostic contains a request-scoped secret Exact credentials and provider-key patterns are redacted before the bounded message is written

How to Review

  1. Start with infra/containers/sandbox/browser-driver/server.js for transport ownership, readiness, and cleanup.
  2. Review infra/containers/sandbox/scripts/start-browser-driver.sh for the credential-delivery boundary.
  3. Review packages/agent-core/src/tools/browser/actions.ts for stale-driver detection.
  4. Confirm the lock and sandbox README match the implementation.

Verification

  • pnpm lint
  • pnpm typecheck
  • pnpm turbo build --force
  • pnpm deadcode
  • pnpm architecture:check
  • pnpm turbo skills:build
  • node --check infra/containers/sandbox/browser-driver/server.js
  • git diff --check
  • Protected immutable sandbox snapshot build
  • Promote the reviewed snapshot in the agent-worker configuration
  • Repeat the production Pomodoro build and browser verification flow
  • Confirm bootstrap credentials are absent from the new Daytona session log
  • Confirm driver termination leaves no owned Chromium process

Scope provider egress controls to AI requests and own Chromium deterministically.

Expose truthful readiness, prevent PTY credential echo, and detect stale drivers quickly.
@iamjr15
iamjr15 merged commit 6c26d68 into main Aug 8, 2026
4 checks passed
@iamjr15
iamjr15 deleted the fix/browser-driver-lifecycle branch August 8, 2026 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant